package com.xquant.trade.trade.service.impl.otcOption;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xquant.common.core.constant.DictConstant;
import com.xquant.common.core.domain.Underlying;
import com.xquant.common.core.exception.ServiceException;
import com.xquant.trade.rocketmq.RocketMqProducer;
import com.xquant.trade.systerm.service.impl.InstrumentServiceImpl;
import com.xquant.trade.trade.entity.BalanceChange;
import com.xquant.trade.trade.entity.Trade;
import com.xquant.trade.trade.entity.TradeStatus;
import com.xquant.trade.trade.mapper.TequityStructureMapper;
import com.xquant.trade.trade.service.impl.TradeServiceAbstract;
import com.xquant.trade.utils.CommResponse;
import com.xquant.trade.utils.DateUtils;
import com.xquant.system.api.SysConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * newCloud 场外期权
 * 场外期权
 */
@Component
public class TradeServiceImpl4OtcOption extends TradeServiceAbstract {

    protected static final Logger logger = LoggerFactory.getLogger(TradeServiceImpl4OtcOption.class);

    @Autowired
    private TequityStructureMapper tequityStructureMapper;

    @Autowired
    RocketMqProducer rocketMqProducer;
    @Autowired
    private InstrumentServiceImpl instrumentService;

    @Resource
    private SysConfigService sysConfigService;


    @Value("${rocketmq.trade-topic}")
    private String tradeTopic;

    /**
     * 交易后 数据准备  【场内交易、期权交易】
     */
    private String afterInsertTrade(Trade trade) {
        String sysConfig = sysConfigService.getSysConfig("cemt");
        String reponse = "";
        return reponse;
    }

    /**
     * newCloud
     * 场外期权  交易类型
     */
    @Override
    public String[] getTradeTypes() {
        return new String[]{
                "OtcOptionBuy",
                "OtcOptionSell"
        };
    }

    /**
     * newCloud
     * 检查 交易信息
     */
    @Override
    public CommResponse checkTrade(Trade trade) {
        super.checkTrade(trade);
        return CommResponse.success();
    }


    /**
     * newCloud
     * 场外期权 新增交易
     */
    @Override
    @Transactional
    public CommResponse insertTrade(Trade trade) {
        trade.setTradeId(DateUtils.getCurr_YYYYMMDDHHMMSSSSS() + RandomUtil.randomNumbers(3));
        Map param = new HashMap();
        param.put("iCode", trade.getiCode());
        param.put("aType", trade.getaType());
        param.put("mType", trade.getmType());
        if (tradeMapper.querySingleTradeContract(param).size() > 0) {
            return CommResponse.failure("合约编号" + trade.getiCode() + "已存在，请检查");
        }
        Map<String, Object> instrumentInfoMap = trade.getInstrumentInfo();
        // 标的信息
        instrumentInfoMap.put("condition", instrumentInfoMap.get("instrumentId"));
        Underlying underlying = instrumentService.selectUnderlyingDatas(instrumentInfoMap).get(0);
        String uICode = underlying.getiCode();
        String uAType = underlying.getaType();
        String uMType = underlying.getmType();


        instrumentInfoMap.put("uIName", underlying.getiName());
        instrumentInfoMap.put("tradeId", trade.getTradeId());
        instrumentInfoMap.put("iCode", trade.getiCode());
        instrumentInfoMap.put("aType", trade.getaType());
        instrumentInfoMap.put("mType", trade.getmType());
        instrumentInfoMap.put("uICode", uICode);
        instrumentInfoMap.put("uAType", uAType);
        instrumentInfoMap.put("uMType", uMType);
        instrumentInfoMap.put("pType", trade.getCalcInstrumentForm().getProductType());
        instrumentInfoMap.put("pClass", trade.getCalcInstrumentForm().getProductType());
        instrumentInfoMap.put("pName", trade.getCalcInstrumentForm().getProductType());
        instrumentInfoMap.put("uInstrument", trade.getCalcInstrumentForm().getInstrumentId());
        instrumentInfoMap.put("exerciseType", trade.getCalcInstrumentForm().getExerciseType());
        instrumentInfoMap.put("payDirection", trade.getCalcInstrumentForm().getPayDirection());
        instrumentInfoMap.put("calendar", trade.getCalendar());
        instrumentInfoMap.put("strike", trade.getCalcInstrumentForm().getStrike());
        instrumentInfoMap.put("pForm", JSONUtil.toJsonStr(trade));
        instrumentInfoMap.put("pFormInstrument", JSONUtil.toJsonStr(trade.getCalcInstrumentForm()));
        instrumentInfoMap.put("pFormPricing", JSONUtil.toJsonStr(trade.getCalcPricingForm()));
        instrumentInfoMap.put("pFormResult", JSONUtil.toJsonStr(trade.getCalcResultForm()));
        if (trade.getCalcInstrumentForm() != null) {
            trade.setPrice(trade.getCalcInstrumentForm().getSpotPrice());
        }
        //20220513 botao.yu 新增字段
        instrumentInfoMap.put("optionType", trade.getOptionType());
        instrumentInfoMap.put("paymentDate", trade.getCalcInstrumentForm().getTerminationPaymentDate());
        instrumentInfoMap.put("price", trade.getPrice());
        instrumentInfoMap.put("frontFee", trade.getFrontFee());
        instrumentInfoMap.put("frontFeePaydate", trade.getFrontFeePaydate());
        instrumentInfoMap.put("frontOptionFee", trade.getFrontOptionFee());
        instrumentInfoMap.put("frontOptionFeePaydate", trade.getFrontOptionFeePaydate());
        instrumentInfoMap.put("terminateDate", trade.getTerminateDate());
        instrumentInfoMap.put("terminateFee", trade.getTerminateFee());
        instrumentInfoMap.put("notional", trade.getCalcInstrumentForm().getNotional());
        /*P013XEQ-1721	交易表新增字段期权费率、 期权费是否年化 、 前端费率、前端费是否年化*/
        instrumentInfoMap.put("frontFeeRate", trade.getFrontFeeRate()); //前端费率
        instrumentInfoMap.put("frontFeeYear", trade.getFrontFeeYear()); //前端费是否年化
        instrumentInfoMap.put("frontOptionFeeRate", trade.getFrontOptionFeeRate());//期权费率
        instrumentInfoMap.put("frontOptionFeeYear", trade.getFrontOptionFeeYear());//期权费是否年化
        /*P013XEQ-1688 期权试定价去掉固定利率字段   去掉了固定利率，因此这里需要注释掉*/
//        instrumentInfoMap.put("fixedRate",trade.getCalcInstrumentForm().getFixedRate() == null ? new BigDecimal(0) : trade.getCalcInstrumentForm().getFixedRate().divide(new BigDecimal(100)));
        String prdType = trade.getCalcInstrumentForm().getProductType().toLowerCase();
        //收益率1
        if (prdType.equals(DictConstant.OPTION_TYPE.VANILLA.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_DIGITAL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.ONE_TOUCH.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.TOUCH.getCode().toLowerCase())
        ) {
            instrumentInfoMap.put("yield1", trade.getCalcInstrumentForm().getPaymentAmountPecentage().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield1", trade.getCalcInstrumentForm().getRebateRate().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield1", trade.getCalcInstrumentForm().getLowRebateRate().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield1", trade.getCalcInstrumentForm().getKnockOutYield().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield1", Double.parseDouble(trade.getCalcInstrumentForm().getSingleSection().getPayOffRate()) / 100);
        } else {
            instrumentInfoMap.put("yield1", 0);
        }
        //收益率2
        if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_DIGITAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getLowPaymentAmountPecentage().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getMidPaymentAmountPecentage().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getMinYieldRate().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getRebateRate().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getUnKnockOutYield().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getSingleSection().getOutPayOffRate().divide(new BigDecimal(100)));
        } else {
            instrumentInfoMap.put("yield2", 0);
        }
        //收益率3
        if (prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield3", trade.getCalcInstrumentForm().getLowPaymentAmountPecentage().divide(new BigDecimal(100)));
        } else {
            instrumentInfoMap.put("yield3", 0);
        }
        //障碍价1
        if (prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice1", NumberUtil.mul(trade.getCalcInstrumentForm().getTriggerRate(), trade.getCalcInstrumentForm().getSpotPrice()).divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice1", NumberUtil.mul(trade.getCalcInstrumentForm().getKonckLevelPercentage(), trade.getCalcInstrumentForm().getSpotPrice()).divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice1", trade.getCalcInstrumentForm().getSingleSection().getCapPrice().divide(new BigDecimal(1)));
        } else {
            instrumentInfoMap.put("triggerPrice1", 0);
        }
        //障碍价2
        if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice2", (NumberUtil.mul(trade.getCalcInstrumentForm().getLowTriggerRate(), trade.getCalcInstrumentForm().getSpotPrice()).divide(new BigDecimal(100))));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice2", (NumberUtil.mul(trade.getCalcInstrumentForm().getKnockInLevelPercentage(), trade.getCalcInstrumentForm().getSpotPrice()).divide(new BigDecimal(100))));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice2", trade.getCalcInstrumentForm().getSingleSection().getFloorPrice().divide(new BigDecimal(1)));
        } else {
            instrumentInfoMap.put("triggerPrice2", 0);
        }
        //参与率1
        if (prdType.equals(DictConstant.OPTION_TYPE.VANILLA.getCode().toLowerCase())
        ) {
            instrumentInfoMap.put("participationRate1", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase()) || (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase()))) {
            instrumentInfoMap.put("participationRate1", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_DIGITAL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.ONE_TOUCH.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.TOUCH.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate1", 0);
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate1", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate1", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else {
            instrumentInfoMap.put("participationRate1", 1);
        }
        //参与率2
        if (prdType.equals(DictConstant.OPTION_TYPE.VANILLA.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", 0);
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DIGITAL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_DIGITAL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.ONE_TOUCH.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.TOUCH.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", 0);
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else {
            instrumentInfoMap.put("participationRate2", 1);
        }
        //行权价
        instrumentInfoMap.put("strikePrice", trade.getCalcInstrumentForm().getStrike());
        instrumentInfoMap.put("lowStrikePrice", trade.getCalcInstrumentForm().getLowStrike());


        try {
            trade.setVersion(1000);
            super.insertTrade(trade);
            tequityStructureMapper.insertTequityStructure(instrumentInfoMap);

        } catch (Exception e) {

        }


        //xpp 优化
        //confirmTrade(trade);
        trade.setTerminationDate(trade.getCalcInstrumentForm().getTerminationDate());
        trade.setIssueDate(trade.getCalcInstrumentForm().getEffectiveDate());

        JSONObject jsonObject = JSONUtil.parseObj(trade);
        //producer.sendTrade("mtradequeue2", jsonObject);
        //发送rocketmq队列
        //20220705 botao.yu 增加消息队列异常捕获 todo
        try {
            //rocketMqProducer.send(tradeTopic, jsonObject);
        } catch (Exception e) {
            //throw new ServiceException(ErrMsgConstant.MQ_ERR);
        }
        // String s = afterInsertTrade(trade);
        return CommResponse.success();
    }

    /**
     * newCloud
     * 场外期权 成交确认
     */
    @Override
    public CommResponse confirmTrade(Trade trade) {
        CommResponse commResponse = CommResponse.success();
        prepareTrade(trade);
        //如果状态不为2，需要更新交易状态

        if (!TradeStatus.DEAL.equals(trade.getTradeStatus())) {
            trade.setTradeStatus(TradeStatus.DEAL);
            tradeMapper.updateTradeStatus(trade);
            // 交易明细
            if (trade.getDetails() != null && trade.getDetails().size() > 0) {
                for (int i = 0; i < trade.getDetails().size(); i++) {
                    trade.getDetails().get(i).setTradeStatus(TradeStatus.DEAL);
                    tradeMapper.updateTradeStatus(trade.getDetails().get(i));
                }
            }
        }
        // 主交易记账
        List<BalanceChange> lst = getBalanceChange(trade);
        for (int i = 0; i < lst.size(); i++) {
            BalanceChange change = lst.get(i);
            change.setMargin(BigDecimal.ZERO);
            if (change.getChangeDate() == null) {
                change.setChangeDate(DateUtils.getCurr_YYYY_MM_DD());
            }
            tradeMapper.insertBalanceChange(change);
            if (change.getChangeDate() != null) {
                commResponse = this.tradeProcessBalanceChange(change);

                if (!commResponse.isSuccess()) {
                    return commResponse;
                }
            }
        }
        if (!commResponse.isSuccess()) {
            return commResponse;
        }
        return commResponse;
    }

    /**
     * newCloud
     * 场外期权 更新
     */
    @Override
    public CommResponse updateTrade(Trade trade) {
        Map instrumentInfoMap = trade.getInstrumentInfo();
        // 标的信息
        String iCode = instrumentInfoMap.get("instrumentId").toString().split(",")[0];
        String aType = instrumentInfoMap.get("instrumentId").toString().split(",")[1];
        String mType = instrumentInfoMap.get("instrumentId").toString().split(",")[2];
        Map map = new HashMap();
        map.put("iCode", iCode);
        map.put("aType", aType);
        map.put("mType", mType);
        List<Map> rt = tradeMapper.getICodeInfo(map);
        if (rt.size() > 0) {
            trade.setuIName(Convert.toStr(rt.get(0).get("I_NAME")));
            instrumentInfoMap.put("uIName", Convert.toStr(rt.get(0).get("I_NAME")));
        }
        instrumentInfoMap.put("iCode", trade.getiCode());
        instrumentInfoMap.put("aType", trade.getaType());
        instrumentInfoMap.put("mType", trade.getmType());
        List<Trade> contractList = tradeMapper.querySingleTradeContract(instrumentInfoMap);
        //如果存在并且交易编号不为本身 则表示合约编号和已存在的其他交易重复
        if (contractList.size() == 1 && !contractList.get(0).getTradeId().equals(trade.getTradeId())) {
            return CommResponse.failure("合约编号\"" + trade.getiCode() + "\"已存在，请检查");
        }
        instrumentInfoMap.put("uICode", iCode);
        instrumentInfoMap.put("uAType", aType);
        instrumentInfoMap.put("uMType", mType);
        instrumentInfoMap.put("uInstrument", trade.getCalcExtraParam().getInstrumentId());
        instrumentInfoMap.put("exerciseType", trade.getCalcExtraParam().getExerciseType());
        instrumentInfoMap.put("payDirection", trade.getCalcExtraParam().getPayDirection());
        instrumentInfoMap.put("calendar", trade.getCalendar());


        instrumentInfoMap.put("tradeId", trade.getTradeId());
        instrumentInfoMap.put("pType", trade.getCalcInstrumentForm().getProductType());
        instrumentInfoMap.put("pClass", trade.getCalcInstrumentForm().getProductType());
        instrumentInfoMap.put("pName", trade.getCalcInstrumentForm().getProductType());
        instrumentInfoMap.put("strike", trade.getCalcInstrumentForm().getStrike());
        instrumentInfoMap.put("pForm", JSONUtil.toJsonStr(trade));
        instrumentInfoMap.put("pFormInstrument", JSONUtil.toJsonStr(trade.getCalcInstrumentForm()));
        instrumentInfoMap.put("pFormPricing", JSONUtil.toJsonStr(trade.getCalcPricingForm()));
        instrumentInfoMap.put("pFormResult", JSONUtil.toJsonStr(trade.getCalcResultForm()));

        //20220513 botao.yu 新增字段
        instrumentInfoMap.put("optionType", trade.getOptionType());
        instrumentInfoMap.put("paymentDate", trade.getCalcInstrumentForm().getTerminationPaymentDate());
        instrumentInfoMap.put("price", trade.getPrice());
        instrumentInfoMap.put("frontFee", trade.getFrontFee());
        /*P013XEQ-1721	交易表新增字段期权费率、 期权费是否年化 、 前端费率、前端费是否年化*/
        instrumentInfoMap.put("frontFeeRate", trade.getFrontFeeRate()); //前端费率
        instrumentInfoMap.put("frontFeeYear", trade.getFrontFeeYear()); //前端费是否年化
        instrumentInfoMap.put("frontOptionFeeRate", trade.getFrontOptionFeeRate());//期权费率
        instrumentInfoMap.put("frontOptionFeeYear", trade.getFrontOptionFeeYear());//期权费是否年化
        instrumentInfoMap.put("frontFeePaydate", trade.getFrontFeePaydate());
        instrumentInfoMap.put("frontOptionFee", trade.getFrontOptionFee());
        instrumentInfoMap.put("frontOptionFeePaydate", trade.getFrontOptionFeePaydate());
        instrumentInfoMap.put("terminateDate", trade.getTerminateDate());
        instrumentInfoMap.put("terminateFee", trade.getTerminateFee());
        instrumentInfoMap.put("notional", trade.getCalcInstrumentForm().getNotional());
        /*P013XEQ-1688 期权试定价去掉固定利率字段   去掉了固定利率，因此这里需要注释掉*/
//        instrumentInfoMap.put("fixedRate", trade.getCalcInstrumentForm().getFixedRate().divide(new BigDecimal(100)));
        String prdType = trade.getCalcInstrumentForm().getProductType().toLowerCase();
        //收益率1
        if (prdType.equals(DictConstant.OPTION_TYPE.VANILLA.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_DIGITAL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.ONE_TOUCH.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.TOUCH.getCode().toLowerCase())
        ) {
            instrumentInfoMap.put("yield1", trade.getCalcInstrumentForm().getPaymentAmountPecentage().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase())) {
            //P013XEQ-1682 单鲨的保底收益填在收益率2里
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getRebateRate().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield1", trade.getCalcInstrumentForm().getLowRebateRate().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield1", trade.getCalcInstrumentForm().getKnockOutYield().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield1", Double.parseDouble(trade.getCalcInstrumentForm().getSingleSection().getPayOffRate()) / 100);
        } else {
            instrumentInfoMap.put("yield1", 0);
        }
        //收益率2
        if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_DIGITAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getLowPaymentAmountPecentage().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getMidPaymentAmountPecentage().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getMinYieldRate().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getRebateRate().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getUnKnockOutYield().divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield2", trade.getCalcInstrumentForm().getSingleSection().getOutPayOffRate().divide(new BigDecimal(100)));
        } else {
            instrumentInfoMap.put("yield2", 0);
        }
        //收益率3
        if (prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("yield3", trade.getCalcInstrumentForm().getLowPaymentAmountPecentage().divide(new BigDecimal(100)));
        } else {
            instrumentInfoMap.put("yield3", 0);
        }
        //障碍价1
        if (prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice1", NumberUtil.mul(trade.getCalcInstrumentForm().getTriggerRate(), trade.getCalcInstrumentForm().getSpotPrice()).divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice1", NumberUtil.mul(trade.getCalcInstrumentForm().getKonckLevelPercentage(), trade.getCalcInstrumentForm().getSpotPrice()).divide(new BigDecimal(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice1", trade.getCalcInstrumentForm().getSingleSection().getCapPrice().divide(new BigDecimal(1)));
        } else {
            instrumentInfoMap.put("triggerPrice1", 0);
        }
        //障碍价2
        if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice2", (NumberUtil.mul(trade.getCalcInstrumentForm().getLowTriggerRate(), trade.getCalcInstrumentForm().getSpotPrice()).divide(new BigDecimal(100))));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice2", (NumberUtil.mul(trade.getCalcInstrumentForm().getKnockInLevelPercentage(), trade.getCalcInstrumentForm().getSpotPrice()).divide(new BigDecimal(100))));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("triggerPrice2", trade.getCalcInstrumentForm().getSingleSection().getFloorPrice().divide(new BigDecimal(1)));
        } else {
            instrumentInfoMap.put("triggerPrice2", 0);
        }
        //参与率1
        if (prdType.equals(DictConstant.OPTION_TYPE.VANILLA.getCode().toLowerCase())
        ) {
            instrumentInfoMap.put("participationRate1", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase()) || (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_SHARK.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase()))) {
            instrumentInfoMap.put("participationRate1", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_DIGITAL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.ONE_TOUCH.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.TOUCH.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate1", 0);
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate1", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate1", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else {
            instrumentInfoMap.put("participationRate1", 1);
        }
        //参与率2
        if (prdType.equals(DictConstant.OPTION_TYPE.VANILLA.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", 0);
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DIGITAL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.SHARK.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_DIGITAL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.MULTI_DIGITAL.getCode().toLowerCase()) ||
                prdType.equals(DictConstant.OPTION_TYPE.ONE_TOUCH.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.TOUCH.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", 0);
        } else if (prdType.equals(DictConstant.OPTION_TYPE.DOUBLE_BARRIER.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_BASICSNOWBALL.getCode().toLowerCase()) || prdType.equals(DictConstant.OPTION_TYPE.ELN_ACB_STANDARDSNOWBALL.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else if (prdType.equals(DictConstant.OPTION_TYPE.RANGEACCRUAL.getCode().toLowerCase())) {
            instrumentInfoMap.put("participationRate2", trade.getCalcInstrumentForm().getParticipationRate().divide(BigDecimal.valueOf(100)));
        } else {
            instrumentInfoMap.put("participationRate2", 1);
        }
        //行权价
        instrumentInfoMap.put("strikePrice", trade.getCalcInstrumentForm().getStrike());
        instrumentInfoMap.put("lowStrikePrice", trade.getCalcInstrumentForm().getLowStrike());


        //@view 乐观锁  保存前进行版本校验 乐观锁的实现方式之一
        Integer version = tradeMapper.queryTradeVersionById(trade.getTradeId());
        if (version != null && trade.getVersion().intValue() == version.intValue()) {
            tequityStructureMapper.updateTequityStructure(instrumentInfoMap);
            trade.setNewVersion(++version);
            CommResponse commResponse = super.updateTrade(trade);
            if (Integer.parseInt(String.valueOf(commResponse.getMsg())) == 0) {
                throw new ServiceException("交易版本已修改，请刷新页面后，再进行修改");
            }
        } else {
            throw new ServiceException("交易版本已修改，请刷新页面后，再进行修改");
        }


        trade.setTerminationDate(trade.getCalcInstrumentForm().getTerminationDate());
        trade.setIssueDate(trade.getCalcInstrumentForm().getEffectiveDate());
        JSONObject jsonObject = JSONUtil.parseObj(trade);
        //发送rabbit队列
        //producer.sendTrade("mtradequeue2", jsonObject);
        //发送rocket队列
        //20220705 botao.yu 增加消息队列异常捕获
        try {
            rocketMqProducer.send(tradeTopic, jsonObject);
        } catch (Exception e) {
            //throw new ServiceException(ErrMsgConstant.MQ_ERR);
        }
        return CommResponse.success();
    }

    /**
     * newCloud
     * 场外期权 撤单前校验
     */
    @Override
    public CommResponse checkRevertTrade(Trade trade) {
        List<Trade> listS = new ArrayList<>();
        List<Trade> list = tradeMapper.queryTradeByMainTrade(trade);
        for (int i = 0; i < list.size(); i++) {
            Trade t = list.get(i);
            if (StrUtil.isEmpty(t.getpTradeId())) {
                listS.add(t);
            }
        }
        if (listS.size() > 0) {
            return new CommResponse(false, "此交易包含子交易，请先撤销子交易！");
        }
        return new CommResponse(true);
    }

    /**
     * newCloud
     * 场外期权 撤单
     */
    @Override
    public void revertTrade(Trade trade) {
        trade.setTradeStatus(TradeStatus.REVERT);
        Map map = trade.getInstrumentInfo();
        map.put("iCode", trade.getiCode());
        map.put("aType", trade.getaType());
        map.put("mType", trade.getmType());
        //更新主交易状态 为 9：作废
        tradeMapper.updateTradeStatus(trade);
        // 删除所有交易明细
        this.tradeDeleteAllBalance(trade);
        // 处理资金变动
        if (TradeStatus.DEAL.equals(trade.getTradeStatus())) {
            BalanceChange cashChangeSelf = new BalanceChange();
            cashChangeSelf.setDimAccId(String.valueOf(trade.getAccId()));
            cashChangeSelf.setChangeDate(trade.getTradeDate());
            this.tradeRollbackBalance(cashChangeSelf);
            this.tradeProcessBalanceChange(cashChangeSelf);
            if (trade.getAccIdCp() != null) {
                BalanceChange cashChangeCp = new BalanceChange();
                cashChangeCp.setDimAccId(String.valueOf(trade.getAccIdCp()));
                cashChangeCp.setChangeDate(trade.getTradeDate());
                this.tradeRollbackBalance(cashChangeSelf);
                this.tradeProcessBalanceChange(cashChangeSelf);
            }
        }
    }

    /**
     * newCloud
     * 场外期权 删除
     */
    @Override
    public void deleteTrade(Trade trade) {
        Map map = trade.getInstrumentInfo();
        map.put("iCode", trade.getiCode());
        map.put("aType", trade.getaType());
        map.put("mType", trade.getmType());
        tequityStructureMapper.deleteTequityStructure(map);
        // 删除所有交易明细
        this.tradeDeleteAllTrade(trade);
        // 处理资金变动
        if (TradeStatus.DEAL.equals(trade.getTradeStatus())) {
            BalanceChange cashChangeSelf = new BalanceChange();
            cashChangeSelf.setDimAccId(String.valueOf(trade.getAccId()));
            cashChangeSelf.setChangeDate(trade.getTradeDate());
            this.tradeRollbackBalance(cashChangeSelf);
//            this.tradeProcessBalanceChange(cashChangeSelf);
            if (trade.getAccIdCp() != null) {
                BalanceChange cashChangeCp = new BalanceChange();
                cashChangeCp.setDimAccId(String.valueOf(trade.getAccIdCp()));
                cashChangeCp.setChangeDate(trade.getTradeDate());
                this.tradeRollbackBalance(cashChangeSelf);
                this.tradeProcessBalanceChange(cashChangeSelf);
            }
        }


    }

    /**
     * newCloud
     * 场外期权 导入 字段配置
     */
    @Override
    public List getTradeColumnCfglist() {
        return null;
    }

    /**
     * newCloud
     * 场外期权 提交审批前 校验
     */
    @Override
    public CommResponse checkBeforeApproval(Trade trade, Map<String, Map> map) {
        CommResponse cmmResponse = super.checkBeforeApproval(trade, map);

        return CommResponse.success();
    }


}
